{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T07:25:42.739178Z",
     "start_time": "2022-05-11T07:25:37.602401Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T07:26:24.965791Z",
     "start_time": "2022-05-11T07:26:24.954820Z"
    }
   },
   "outputs": [],
   "source": [
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T07:28:09.864122Z",
     "start_time": "2022-05-11T07:28:09.845170Z"
    }
   },
   "outputs": [],
   "source": [
    "base_dir = './data/cats_and_dogs'\n",
    "train_dir = os.path.join(base_dir, 'train')\n",
    "validation_dir = os.path.join(base_dir, 'validation')\n",
    "\n",
    "# 训练集\n",
    "train_cats_dir = os.path.join(train_dir, 'cats')\n",
    "train_dogs_dir = os.path.join(train_dir, 'dogs')\n",
    "\n",
    "# 验证集\n",
    "validation_cats_dir = os.path.join(validation_dir, 'cats')\n",
    "validation_dogs_dir = os.path.join(validation_dir, 'dogs')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T07:30:03.647372Z",
     "start_time": "2022-05-11T07:30:03.634407Z"
    }
   },
   "outputs": [],
   "source": [
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T07:31:37.710795Z",
     "start_time": "2022-05-11T07:31:37.690694Z"
    }
   },
   "outputs": [],
   "source": [
    "# ImageDataGenerator 图片生成器, 会自动的帮我们从指定目录中读取图片. \n",
    "train_datagen = ImageDataGenerator(rescale=1./255)\n",
    "valid_datagen = ImageDataGenerator(rescale=1./255)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T07:49:37.678026Z",
     "start_time": "2022-05-11T07:49:36.930026Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 2000 images belonging to 2 classes.\n",
      "Found 1000 images belonging to 2 classes.\n"
     ]
    }
   ],
   "source": [
    "train_generator = train_datagen.flow_from_directory(\n",
    "    train_dir, # 文件夹路径\n",
    "    target_size=(64, 64),  # 指定图片缩放之后的大小\n",
    "    batch_size=20,\n",
    "    # 默认是categorical,表示多分类, 二分类用binary\n",
    "    class_mode='binary')\n",
    "\n",
    "validation_generator = valid_datagen.flow_from_directory(\n",
    "    validation_dir, # 文件夹路径\n",
    "    target_size=(64, 64),  # 指定图片缩放之后的大小\n",
    "    batch_size=20,\n",
    "    # 默认是categorical,表示多分类, 二分类用binary\n",
    "    class_mode='binary')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T08:03:41.633271Z",
     "start_time": "2022-05-11T08:03:41.543510Z"
    }
   },
   "outputs": [],
   "source": [
    "# 搭建卷积神经网络\n",
    "model = tf.keras.models.Sequential()\n",
    "# 2次卷积一次池化, 3层, 2层全连接. \n",
    "model.add(tf.keras.layers.Conv2D(filters=32, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu',\n",
    "                                 input_shape=(64, 64, 3)))\n",
    "model.add(tf.keras.layers.Conv2D(filters=32, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu'))\n",
    "model.add(tf.keras.layers.MaxPool2D(pool_size=2))\n",
    "\n",
    "model.add(tf.keras.layers.Conv2D(filters=64, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu'))\n",
    "model.add(tf.keras.layers.Conv2D(filters=64, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu'))\n",
    "model.add(tf.keras.layers.MaxPool2D(pool_size=2))\n",
    "\n",
    "model.add(tf.keras.layers.Conv2D(filters=128, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu'))\n",
    "model.add(tf.keras.layers.Conv2D(filters=128, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu'))\n",
    "model.add(tf.keras.layers.MaxPool2D(pool_size=2))\n",
    "\n",
    "model.add(tf.keras.layers.Flatten())\n",
    "model.add(tf.keras.layers.Dense(512, activation='relu'))\n",
    "model.add(tf.keras.layers.Dense(256, activation='relu'))\n",
    "model.add(tf.keras.layers.Dense(1, activation='sigmoid'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T07:45:01.092217Z",
     "start_time": "2022-05-11T07:45:00.986427Z"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential_2\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d_6 (Conv2D)            (None, 64, 64, 32)        896       \n",
      "_________________________________________________________________\n",
      "conv2d_7 (Conv2D)            (None, 64, 64, 32)        9248      \n",
      "_________________________________________________________________\n",
      "max_pooling2d_3 (MaxPooling2 (None, 32, 32, 32)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_8 (Conv2D)            (None, 32, 32, 64)        18496     \n",
      "_________________________________________________________________\n",
      "conv2d_9 (Conv2D)            (None, 32, 32, 64)        36928     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_4 (MaxPooling2 (None, 16, 16, 64)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_10 (Conv2D)           (None, 16, 16, 128)       73856     \n",
      "_________________________________________________________________\n",
      "conv2d_11 (Conv2D)           (None, 16, 16, 128)       147584    \n",
      "_________________________________________________________________\n",
      "max_pooling2d_5 (MaxPooling2 (None, 8, 8, 128)         0         \n",
      "_________________________________________________________________\n",
      "flatten_1 (Flatten)          (None, 8192)              0         \n",
      "_________________________________________________________________\n",
      "dense (Dense)                (None, 512)               4194816   \n",
      "_________________________________________________________________\n",
      "dense_1 (Dense)              (None, 256)               131328    \n",
      "_________________________________________________________________\n",
      "dense_2 (Dense)              (None, 1)                 257       \n",
      "=================================================================\n",
      "Total params: 4,613,409\n",
      "Trainable params: 4,613,409\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T08:03:45.742795Z",
     "start_time": "2022-05-11T08:03:45.717860Z"
    }
   },
   "outputs": [],
   "source": [
    "model.compile(loss='binary_crossentropy',\n",
    "             optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),\n",
    "             metrics=['acc'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T08:04:44.132604Z",
     "start_time": "2022-05-11T08:03:48.185261Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/20\n",
      "100/100 [==============================] - 4s 30ms/step - loss: 0.6933 - acc: 0.5003 - val_loss: 0.6881 - val_acc: 0.5060\n",
      "Epoch 2/20\n",
      "100/100 [==============================] - 3s 28ms/step - loss: 0.6768 - acc: 0.5654 - val_loss: 0.6393 - val_acc: 0.6350\n",
      "Epoch 3/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.6194 - acc: 0.6684 - val_loss: 0.6204 - val_acc: 0.6710\n",
      "Epoch 4/20\n",
      "100/100 [==============================] - 3s 28ms/step - loss: 0.5548 - acc: 0.7294 - val_loss: 0.6026 - val_acc: 0.6830\n",
      "Epoch 5/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.5452 - acc: 0.7311 - val_loss: 0.5963 - val_acc: 0.6780\n",
      "Epoch 6/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.5030 - acc: 0.7309 - val_loss: 0.5598 - val_acc: 0.7350\n",
      "Epoch 7/20\n",
      "100/100 [==============================] - 3s 28ms/step - loss: 0.4529 - acc: 0.7920 - val_loss: 0.5633 - val_acc: 0.7250\n",
      "Epoch 8/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.4246 - acc: 0.8073 - val_loss: 0.5689 - val_acc: 0.7230\n",
      "Epoch 9/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.4018 - acc: 0.8248 - val_loss: 0.5549 - val_acc: 0.7270\n",
      "Epoch 10/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.3472 - acc: 0.8424 - val_loss: 0.5491 - val_acc: 0.7370\n",
      "Epoch 11/20\n",
      "100/100 [==============================] - 3s 28ms/step - loss: 0.3243 - acc: 0.8573 - val_loss: 0.5775 - val_acc: 0.7280\n",
      "Epoch 12/20\n",
      "100/100 [==============================] - 3s 28ms/step - loss: 0.2770 - acc: 0.8870 - val_loss: 0.6722 - val_acc: 0.7200\n",
      "Epoch 13/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.2264 - acc: 0.9046 - val_loss: 0.6584 - val_acc: 0.7470\n",
      "Epoch 14/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.1956 - acc: 0.9247 - val_loss: 0.6828 - val_acc: 0.7400\n",
      "Epoch 15/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.1288 - acc: 0.9508 - val_loss: 0.7735 - val_acc: 0.7290\n",
      "Epoch 16/20\n",
      "100/100 [==============================] - 3s 28ms/step - loss: 0.1085 - acc: 0.9670 - val_loss: 0.7551 - val_acc: 0.7400\n",
      "Epoch 17/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.1228 - acc: 0.9540 - val_loss: 0.9157 - val_acc: 0.7300\n",
      "Epoch 18/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.0789 - acc: 0.9710 - val_loss: 0.9311 - val_acc: 0.7560\n",
      "Epoch 19/20\n",
      "100/100 [==============================] - 3s 28ms/step - loss: 0.0217 - acc: 0.9979 - val_loss: 0.9941 - val_acc: 0.7270\n",
      "Epoch 20/20\n",
      "100/100 [==============================] - 3s 27ms/step - loss: 0.0207 - acc: 0.9946 - val_loss: 1.0781 - val_acc: 0.7470\n"
     ]
    }
   ],
   "source": [
    "history = model.fit(train_generator, \n",
    "                    steps_per_epoch=100, # 2000 images : = batch_size * steps\n",
    "                    epochs=20,\n",
    "                    validation_data=validation_generator,\n",
    "                    validation_steps=50, # 1000 images = batch_size * steps\n",
    "                   )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T08:05:53.845373Z",
     "start_time": "2022-05-11T08:05:53.710390Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pd.DataFrame(history.history).plot(figsize=(8, 5))\n",
    "plt.grid()\n",
    "plt.gca().set_ylim(0, 1)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T08:11:32.611080Z",
     "start_time": "2022-05-11T08:11:32.281959Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 2000 images belonging to 2 classes.\n",
      "Found 1000 images belonging to 2 classes.\n"
     ]
    }
   ],
   "source": [
    "# 数据增强\n",
    "train_datagen = ImageDataGenerator(rescale=1./255,\n",
    "                                  rotation_range=40, \n",
    "                                  width_shift_range=0.2,\n",
    "                                  height_shift_range=0.2,\n",
    "                                  shear_range=0.2,\n",
    "                                  zoom_range=0.2,\n",
    "                                  horizontal_flip=True,\n",
    "                                  fill_mode='nearest')\n",
    "valid_datagen = ImageDataGenerator(rescale=1./255)\n",
    "train_generator = train_datagen.flow_from_directory(\n",
    "    train_dir, # 文件夹路径\n",
    "    target_size=(64, 64),  # 指定图片缩放之后的大小\n",
    "    batch_size=20,\n",
    "    # 默认是categorical,表示多分类, 二分类用binary\n",
    "    class_mode='binary')\n",
    "\n",
    "validation_generator = valid_datagen.flow_from_directory(\n",
    "    validation_dir, # 文件夹路径\n",
    "    target_size=(64, 64),  # 指定图片缩放之后的大小\n",
    "    batch_size=20,\n",
    "    # 默认是categorical,表示多分类, 二分类用binary\n",
    "    class_mode='binary')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T08:13:30.517336Z",
     "start_time": "2022-05-11T08:11:58.624543Z"
    },
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/20\n",
      "100/100 [==============================] - 5s 47ms/step - loss: 0.6934 - acc: 0.4989 - val_loss: 0.6905 - val_acc: 0.5040\n",
      "Epoch 2/20\n",
      "100/100 [==============================] - 5s 47ms/step - loss: 0.6930 - acc: 0.5108 - val_loss: 0.6845 - val_acc: 0.5280\n",
      "Epoch 3/20\n",
      "100/100 [==============================] - 4s 44ms/step - loss: 0.6867 - acc: 0.5560 - val_loss: 0.6446 - val_acc: 0.6200\n",
      "Epoch 4/20\n",
      "100/100 [==============================] - 4s 45ms/step - loss: 0.6524 - acc: 0.6232 - val_loss: 0.6780 - val_acc: 0.5750\n",
      "Epoch 5/20\n",
      "100/100 [==============================] - 4s 44ms/step - loss: 0.6736 - acc: 0.5856 - val_loss: 0.6043 - val_acc: 0.6770\n",
      "Epoch 6/20\n",
      "100/100 [==============================] - 4s 44ms/step - loss: 0.6133 - acc: 0.6503 - val_loss: 0.5926 - val_acc: 0.6860\n",
      "Epoch 7/20\n",
      "100/100 [==============================] - 4s 44ms/step - loss: 0.6189 - acc: 0.6653 - val_loss: 0.6047 - val_acc: 0.6670\n",
      "Epoch 8/20\n",
      "100/100 [==============================] - 5s 46ms/step - loss: 0.6108 - acc: 0.6662 - val_loss: 0.5849 - val_acc: 0.6740\n",
      "Epoch 9/20\n",
      "100/100 [==============================] - 5s 46ms/step - loss: 0.5685 - acc: 0.6985 - val_loss: 0.5654 - val_acc: 0.7070\n",
      "Epoch 10/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.5980 - acc: 0.6622 - val_loss: 0.5646 - val_acc: 0.6970\n",
      "Epoch 11/20\n",
      "100/100 [==============================] - 5s 46ms/step - loss: 0.5759 - acc: 0.6879 - val_loss: 0.5836 - val_acc: 0.6910\n",
      "Epoch 12/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.5805 - acc: 0.6865 - val_loss: 0.5640 - val_acc: 0.7060\n",
      "Epoch 13/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.5733 - acc: 0.6967 - val_loss: 0.5808 - val_acc: 0.6820\n",
      "Epoch 14/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.5779 - acc: 0.6857 - val_loss: 0.6307 - val_acc: 0.6680\n",
      "Epoch 15/20\n",
      "100/100 [==============================] - 4s 45ms/step - loss: 0.5498 - acc: 0.7178 - val_loss: 0.5564 - val_acc: 0.7050\n",
      "Epoch 16/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.5561 - acc: 0.7016 - val_loss: 0.6625 - val_acc: 0.6450\n",
      "Epoch 17/20\n",
      "100/100 [==============================] - 4s 45ms/step - loss: 0.5513 - acc: 0.7060 - val_loss: 0.5414 - val_acc: 0.7160\n",
      "Epoch 18/20\n",
      "100/100 [==============================] - 4s 45ms/step - loss: 0.5293 - acc: 0.7339 - val_loss: 0.5329 - val_acc: 0.7300\n",
      "Epoch 19/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.5344 - acc: 0.7272 - val_loss: 0.5141 - val_acc: 0.7410\n",
      "Epoch 20/20\n",
      "100/100 [==============================] - 5s 48ms/step - loss: 0.5257 - acc: 0.7146 - val_loss: 0.5461 - val_acc: 0.7240\n"
     ]
    }
   ],
   "source": [
    "# 搭建卷积神经网络\n",
    "model = tf.keras.models.Sequential()\n",
    "# 2次卷积一次池化, 3层, 2层全连接. \n",
    "model.add(tf.keras.layers.Conv2D(filters=32, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu',\n",
    "                                 input_shape=(64, 64, 3)))\n",
    "model.add(tf.keras.layers.Conv2D(filters=32, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu'))\n",
    "model.add(tf.keras.layers.MaxPool2D(pool_size=2))\n",
    "\n",
    "model.add(tf.keras.layers.Conv2D(filters=64, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu'))\n",
    "model.add(tf.keras.layers.Conv2D(filters=64, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu'))\n",
    "model.add(tf.keras.layers.MaxPool2D(pool_size=2))\n",
    "\n",
    "model.add(tf.keras.layers.Conv2D(filters=128, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu'))\n",
    "model.add(tf.keras.layers.Conv2D(filters=128, \n",
    "                                 kernel_size=3,\n",
    "                                 padding='same',\n",
    "                                 activation='relu'))\n",
    "model.add(tf.keras.layers.MaxPool2D(pool_size=2))\n",
    "\n",
    "model.add(tf.keras.layers.Flatten())\n",
    "model.add(tf.keras.layers.Dense(512, activation='relu'))\n",
    "model.add(tf.keras.layers.Dense(256, activation='relu'))\n",
    "model.add(tf.keras.layers.Dense(1, activation='sigmoid'))\n",
    "\n",
    "model.compile(loss='binary_crossentropy',\n",
    "             optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),\n",
    "             metrics=['acc'])\n",
    "\n",
    "history = model.fit(train_generator, \n",
    "                    steps_per_epoch=100, # 2000 images : = batch_size * steps\n",
    "                    epochs=20,\n",
    "                    validation_data=validation_generator,\n",
    "                    validation_steps=50, # 1000 images = batch_size * steps\n",
    "                   )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-05-11T08:16:55.876164Z",
     "start_time": "2022-05-11T08:15:24.745513Z"
    },
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/20\n",
      "100/100 [==============================] - 5s 47ms/step - loss: 0.5291 - acc: 0.7345 - val_loss: 0.5312 - val_acc: 0.7310\n",
      "Epoch 2/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.5126 - acc: 0.7400 - val_loss: 0.5147 - val_acc: 0.7490\n",
      "Epoch 3/20\n",
      "100/100 [==============================] - 4s 45ms/step - loss: 0.5192 - acc: 0.7385 - val_loss: 0.4972 - val_acc: 0.7420\n",
      "Epoch 4/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.5124 - acc: 0.7465 - val_loss: 0.5264 - val_acc: 0.7170\n",
      "Epoch 5/20\n",
      "100/100 [==============================] - 4s 45ms/step - loss: 0.5141 - acc: 0.7485 - val_loss: 0.4969 - val_acc: 0.7450\n",
      "Epoch 6/20\n",
      "100/100 [==============================] - 5s 46ms/step - loss: 0.5048 - acc: 0.7400 - val_loss: 0.5044 - val_acc: 0.7460\n",
      "Epoch 7/20\n",
      "100/100 [==============================] - 5s 46ms/step - loss: 0.4905 - acc: 0.7610 - val_loss: 0.5057 - val_acc: 0.7400\n",
      "Epoch 8/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.4864 - acc: 0.7620 - val_loss: 0.4977 - val_acc: 0.7380\n",
      "Epoch 9/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.4972 - acc: 0.7585 - val_loss: 0.5027 - val_acc: 0.7530\n",
      "Epoch 10/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.4959 - acc: 0.7660 - val_loss: 0.4850 - val_acc: 0.7570\n",
      "Epoch 11/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.4816 - acc: 0.7655 - val_loss: 0.4954 - val_acc: 0.7440\n",
      "Epoch 12/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.4731 - acc: 0.7750 - val_loss: 0.5530 - val_acc: 0.7060\n",
      "Epoch 13/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.4826 - acc: 0.7625 - val_loss: 0.4668 - val_acc: 0.7700\n",
      "Epoch 14/20\n",
      "100/100 [==============================] - 4s 45ms/step - loss: 0.4625 - acc: 0.7865 - val_loss: 0.4852 - val_acc: 0.7580\n",
      "Epoch 15/20\n",
      "100/100 [==============================] - 4s 45ms/step - loss: 0.4678 - acc: 0.7830 - val_loss: 0.4709 - val_acc: 0.7690\n",
      "Epoch 16/20\n",
      "100/100 [==============================] - 5s 46ms/step - loss: 0.4590 - acc: 0.7835 - val_loss: 0.4554 - val_acc: 0.7730\n",
      "Epoch 17/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.4528 - acc: 0.7985 - val_loss: 0.4717 - val_acc: 0.7680\n",
      "Epoch 18/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.4524 - acc: 0.7755 - val_loss: 0.4518 - val_acc: 0.7750\n",
      "Epoch 19/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.4543 - acc: 0.7825 - val_loss: 0.4612 - val_acc: 0.7780\n",
      "Epoch 20/20\n",
      "100/100 [==============================] - 5s 45ms/step - loss: 0.4376 - acc: 0.8035 - val_loss: 0.5148 - val_acc: 0.7710\n"
     ]
    }
   ],
   "source": [
    "history = model.fit(train_generator, \n",
    "                    steps_per_epoch=100, # 2000 images : = batch_size * steps\n",
    "                    epochs=20,\n",
    "                    validation_data=validation_generator,\n",
    "                    validation_steps=50, # 1000 images = batch_size * steps\n",
    "                   )"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
